package com.ailk.cuc.autotestbg.xml.business.impl.ecs;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;

import com.ailk.cuc.autotestbg.common.bean.AutoCaseResultBGBean;
import com.ailk.cuc.autotestbg.common.bean.AutoCaseStepBGBean;
import com.ailk.cuc.autotestbg.common.bean.AutoStepResultBGBean;
import com.ailk.cuc.autotestbg.common.bean.AutoStepResultDetailBGBean;
import com.ailk.cuc.autotestbg.common.business.interf.SendOutComponentInterface;
import com.ailk.cuc.autotestbg.common.exception.DataBaseException;
import com.ailk.cuc.autotestbg.common.utils.LogUtils;
import com.ailk.cuc.autotestbg.common.utils.MessageUtil;
import com.ailk.cuc.autotestbg.common.utils.SpringContextUtil;
import com.ailk.cuc.autotestbg.common.utils.StringFormatUtils;
import com.ailk.cuc.autotestbg.xml.bean.AutoEssDataBean;
import com.ailk.cuc.autotestbg.xml.bean.AutoEssInterfaceBean;
import com.ailk.cuc.autotestbg.xml.exception.EcsSendOutException;
import com.ibatis.sqlmap.client.SqlMapClient;

public class EcsSendOutComponentImpl implements SendOutComponentInterface {
	
	private static Log logger = LogUtils.getLogger(EcsSendOutComponentImpl.class.getName());

	public void sendOutInfo(Map<String, Object> argMapIn,Map<String, Object> argMapOut) throws EcsSendOutException {
		
		try {
			AutoEssDataBean ecsDataBean = (AutoEssDataBean)argMapIn.get("ecsDataBean");
			
			SqlMapClient sqlMapClient = (SqlMapClient)SpringContextUtil.getBean("sqlMapClient");
			
			AutoCaseResultBGBean caseResultBGBean = (AutoCaseResultBGBean)argMapIn.get("caseResultBGBean");
			AutoCaseStepBGBean caseStepBean = (AutoCaseStepBGBean) argMapIn.get("caseStepBean");
			AutoStepResultBGBean stepResultBGBean = new AutoStepResultBGBean();
			AutoStepResultDetailBGBean stepResultDetailBGBean =  new AutoStepResultDetailBGBean();
			
			//写入结果表的步骤，分为如下几步
			//1.发送之前，先写入结果表 
			insertStepResultBGBean(stepResultBGBean, caseResultBGBean, caseStepBean, sqlMapClient);
			
			AutoEssInterfaceBean ecsInterfaceBean = null;
			try {
				ecsInterfaceBean = (AutoEssInterfaceBean)sqlMapClient.queryForObject("xml_ess_ecs_assembly.getEssInterfaceBean",ecsDataBean);
			} catch (SQLException e) {
				logger.error("EcsSendOutComponentImpl.sendOutInfo方法异常");
				logger.error(e.getMessage());
				throw new DataBaseException("ECS发送报文之前，获取essInterface数据操作异常");
			}
			
			String ecsMessageXml = (String)argMapIn.get(ecsDataBean.getInterfaceId()+"_request_"+"ecsMessageXml");

			logger.info("ECS发送报文开始");
			String ecsResponseXml = sendOutEcsRequestMessage(ecsInterfaceBean,ecsMessageXml);
			logger.info("ECS接收报文结束");
			
			argMapIn.put(ecsDataBean.getInterfaceId()+"_response_"+"ecsMessageXml", ecsResponseXml);
			
			//处理接收到的报文，主要是做验证使用
			String expectResult = ecsDataBean.getExpectResult();
			checkEssResponseIsRight(expectResult, ecsResponseXml,stepResultDetailBGBean);
			String handleData = StringFormatUtils.formatLong("%1$06d", caseStepBean.getTestCaseId())+" "+ecsDataBean.getInterfaceId()+ecsMessageXml;
			stepResultDetailBGBean.setHandleData(handleData.length()>3900?handleData.substring(0, 3900):handleData);
			
			//2.接收到返回的报文，并经过处理之后，写入StepResultDetail表
			insertStepResultDetailBGBean(stepResultDetailBGBean, stepResultBGBean, sqlMapClient);
			
			//3.更新stepResultBGBean
			updateStepResultBGBean(stepResultBGBean, stepResultDetailBGBean, sqlMapClient);
			
			
			//获取下一个caseStep
			AutoCaseStepBGBean nextCaseStepBean = null;
			AutoEssDataBean nextEcsDataBean = null;
			try {
				nextCaseStepBean = (AutoCaseStepBGBean)sqlMapClient.queryForObject("xml_ess_ecs_sendout.getNextCaseStepByUp",caseStepBean);
				if(nextCaseStepBean != null){
					String dataId = nextCaseStepBean.getInputDataId()+"";
					nextEcsDataBean = (AutoEssDataBean)sqlMapClient.queryForObject("xml_ess_ecs_assembly.getEssDatabean",dataId);
				}
			} catch (SQLException e) {
				logger.error("EcsSendOutComponentImpl.sendOutInfo方法异常");
				logger.error(e.getMessage());
				throw new DataBaseException("ECS发送报文完成，获取下一步数据操作异常");
			}
			argMapIn.put("ecsDataBean", nextEcsDataBean);
			argMapIn.put("caseStepBean", nextCaseStepBean);
			
			//4.更新caseResultBGBean
			updateCaseResultBGBean(caseResultBGBean, sqlMapClient);
			
			//将入参传递给出参
			argMapOut.putAll(argMapIn);
		} catch (DataBaseException e) {
			logger.error("ECS发送报文发生异常");
			logger.error(e.getMessage());
			throw new EcsSendOutException("发送报文时发生数据库操作异常");
		}
	}

	public String sendOutEcsRequestMessage(AutoEssInterfaceBean essInterfaceBean,String ecsMessageXml){
		StringBuilder essResponseXml = new StringBuilder("");
		String ecsResponseMessage = "";
		OutputStreamWriter out = null;
		BufferedReader br = null;
		try {
			URL url = new URL(essInterfaceBean.getAddress());
			URLConnection con = url.openConnection();
			con.setDoOutput(true);
			con.setDoInput(true);
			con.setUseCaches(false);
			logger.info("将全业务报文转发至:"+essInterfaceBean.getAddress());
			
			//Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7
			//con.setRequestProperty("Accept-Charset", "utf-8");
			out = new OutputStreamWriter(con.getOutputStream(),"UTF-8");
			String UTF8Message = new String(ecsMessageXml.getBytes("UTF-8"),"UTF-8");
			out.write(UTF8Message);
			out.flush();
			
			br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
			String line = "";
			
			for (line = br.readLine(); line != null; line = br.readLine()) {
				essResponseXml.append(line);
			}
			int i = essResponseXml.indexOf("</ns4:UNI_BSS_ATTACHED>");
			if (i > 0) {
				String top = essResponseXml.substring(0, essResponseXml.indexOf("</UNI_BSS_HEAD>") + 15);
				String bottom = essResponseXml.substring(essResponseXml.indexOf("</ns4:UNI_BSS_ATTACHED>") + 23);
				String code = essResponseXml.substring(essResponseXml.indexOf("<ns4:MEDIA_INFO>") + 16, essResponseXml.indexOf("</ns4:MEDIA_INFO>"));
				String uncode = MessageUtil.uncompress(code);
				
				ecsResponseMessage = essResponseXml.delete(0, essResponseXml.length()).append(top).append(bottom).append(uncode).toString();
			}else{
				ecsResponseMessage = essResponseXml.toString();
			}
		} catch (MalformedURLException e) {
			// 发生URL协议、格式、路径错误或异常
			ecsResponseMessage = "       7";
			logger.error("URL协议、格式、路径错误或异常！");
			logger.error(e.getMessage());
		} catch (UnsupportedEncodingException e) {
			// 发生编码异常
			ecsResponseMessage = "       8";
			logger.error("编码异常！");
			logger.error(e.getMessage());
		} catch (IOException e) {
			// 发生网络异常
			ecsResponseMessage = "       6";
			logger.error("网络异常！");
			logger.error(e.getMessage());
		}finally{
			try {
				out.close();
				br.close();
			} catch (IOException e) {
				// 发生网络异常
				ecsResponseMessage = "       6";
				logger.error("关闭网络IO流异常！");
				logger.error(e.getMessage());
			}
		}
		logger.info("收到的报文信息："+ecsResponseMessage);
		return ecsResponseMessage;
	}
	
	public void insertStepResultBGBean(AutoStepResultBGBean stepResultBGBean, AutoCaseResultBGBean caseResultBGBean,AutoCaseStepBGBean caseStepBean,SqlMapClient sqlMapClient) throws DataBaseException{

		stepResultBGBean.setTaskId(caseResultBGBean.getTaskId());
		stepResultBGBean.setTestNo(caseResultBGBean.getTestNo());
		stepResultBGBean.setSeqId(caseStepBean.getSeqId());
		stepResultBGBean.setStepName(caseStepBean.getStepName());

		try {
			sqlMapClient.insert("common_result.insertStepResultBGBean",stepResultBGBean);
		} catch (SQLException e) {
			logger.error("EcsSendOutComponentImpl.insertStepResultBGBean方法异常");
			logger.error(e.getMessage());
			throw new DataBaseException("ECS发送报文插入StepResult数据操作异常");
		}

	}
	
	public void insertStepResultDetailBGBean(AutoStepResultDetailBGBean stepResultDetailBGBean ,AutoStepResultBGBean stepResultBGBean, SqlMapClient sqlMapClient) throws DataBaseException{

		stepResultDetailBGBean.setTaskId(stepResultBGBean.getTaskId());
		stepResultDetailBGBean.setTestNo(stepResultBGBean.getTestNo());
		stepResultDetailBGBean.setSeqId(stepResultBGBean.getSeqId());
		stepResultDetailBGBean.setType(2+"");


		try {
//			long serialId = (Long)sqlMapClient.queryForObject("common_result.getStepResultDetailSerialIdBySeq");
//			stepResultDetailBGBean.setSerialId(serialId);
			sqlMapClient.insert("common_result.insertStepResultDetailBGBean",stepResultDetailBGBean);
		} catch (SQLException e) {
			logger.error("EcsSendOutComponentImpl.insertStepResultDetailBGBean方法异常");
			logger.error(e.getMessage());
			throw new DataBaseException("ECS发送报文插入StepResultDetail数据操作异常");
		}

	}

	@SuppressWarnings("unchecked")
	public void checkEssResponseIsRight(String expectResult,String ecsResponseXml,AutoStepResultDetailBGBean stepResultDetailBGBean){
		boolean right = true;
		StringBuilder realResult = new StringBuilder("");
		SAXReader reader = new SAXReader();
		Element root = null;
		Element body = null;
		Element serBody = null;
		

		stepResultDetailBGBean.setExpectData(expectResult==null?"":expectResult);

		try {
			if(expectResult!=null && !"".equals(expectResult)){

				if(ecsResponseXml != null && !"".equals(ecsResponseXml)){

					org.dom4j.Document doc = reader.read(new InputSource(new StringReader(ecsResponseXml)));
					root = doc.getRootElement();
					if(root != null){
						body = root.element("Body");
					}
					if(body != null){
						List<Element> eleList = body.elements();
						if(eleList != null){
							for(Element element : eleList){
								//只找第一个子结点
								serBody = element;
								break;
							}
						}
					}
					if(root != null && body != null && serBody != null){
						
						String[] expectResultArray = expectResult.split("\\^");
						for(String expectResultStr : expectResultArray){
							
							String[] expectResultKeyAndValue = expectResultStr.split("=");
							String expectResultKey = "";
							String expectResultValue = "";
							//对期望结果值格式不正确的处理
							if(expectResultKeyAndValue.length != 2){
								expectResultValue = expectResultKeyAndValue[0];
								expectResultKey = expectResultKeyAndValue[0];
								right = false;
							}else{
								expectResultKey = expectResultKeyAndValue[0];
								expectResultValue = expectResultKeyAndValue[1];
							}
							
							String[] expectResultKeyCompArray = expectResultKey.split("\\.");
							Element currentElement = serBody;
							for(String keyComp : expectResultKeyCompArray){
								if(currentElement != null){
									currentElement = currentElement.element(keyComp.trim());
								}else{
									right = false;
									break;
								}
							}
							
							if(currentElement != null){
								String respCodeValue = currentElement.getText();
								if(right){
									if(respCodeValue != null){
										right = expectResultValue.trim().indexOf(respCodeValue.trim())!=-1?true:false; 
									}else{
										right = false;
									}
								}
								realResult.append(expectResultKey).append("=").append(respCodeValue == null ? "recv null" : respCodeValue).append(";");
							}else{
								right = false;
								realResult.append(expectResultKey).append("=").append("recv null").append(";");
							}
							
						}
					}else{
						right = false;
						realResult.append("The Resp Xml body is null ;");
					}

				}else{
					right = false;
					realResult.append("The Resp Xml is Null Or unavailable :[]").append(";");
				}
			}else{
				//如果是没有比对结果值，则默认比对成功
				right = true;
			}

			stepResultDetailBGBean.setStatus(right?"1":"2");
			stepResultDetailBGBean.setRealData(realResult.toString());
		} catch (DocumentException e) {
			logger.error("解析返回的XML报文发生异常");
			logger.error(e.getMessage());
			e.printStackTrace();
			stepResultDetailBGBean.setStatus("2");
			stepResultDetailBGBean.setRealData("java parser response message exception");
		}
	}

	public void updateStepResultBGBean(AutoStepResultBGBean stepResultBGBean,AutoStepResultDetailBGBean stepResultDetailBGBean,SqlMapClient sqlMapClient) throws DataBaseException{
		if("1".equals(stepResultDetailBGBean.getStatus())){
			stepResultBGBean.setIsRight("Y");
			stepResultBGBean.setErrorDesc("");
		}else{
			stepResultBGBean.setIsRight("N");
			stepResultBGBean.setErrorDesc(stepResultDetailBGBean.getRealData());
		}
		try {
			sqlMapClient.update("common_result.updateStepResultBGBean",stepResultBGBean);
		} catch (SQLException e) {
			logger.error("EcsSendOutComponentImpl.updateStepResultBGBean方法异常");
			logger.error(e.getMessage());
			throw new DataBaseException("ECS发送报文更新StepResult数据操作异常");
		}

	}
	
	public void updateCaseResultBGBean(AutoCaseResultBGBean caseResultBGBean,SqlMapClient sqlMapClient) throws DataBaseException{
		caseResultBGBean.setOverStepNum(caseResultBGBean.getOverStepNum()+1);
		try {
			sqlMapClient.update("common_result.updateCaseResultBGBean",caseResultBGBean);
		} catch (SQLException e) {
			logger.error("EcsSendOutComponentImpl.updateCaseResultBGBean方法异常");
			logger.error(e.getMessage());
			throw new DataBaseException("ECS发送报文更新CaseResult数据操作异常");
		}
	}
}
